#include "DemoCreaeFixture.h"
#include"LSYEasyBody.h"
#include"LSYEasyWorld.h"
#include"Box2D\Box2D.h"
#include"GLES-Render.h"
#include"Tool.h"
#include<random>
#include<algorithm>

USING_NS_CC;
using namespace std;

bool DemoCreateFixture::init()
{
	if (!AbstractBox2DTest::init(b2Vec2(0, -10)))
	{
		return false;
	}
	auto size = Director::getInstance()->getWinSize();
	LSYEasyBody::createRectangle(b2Vec2(0, 0), size.width, size.height);
	schedule(schedule_selector(DemoCreateFixture::work), 1.0f, CC_REPEAT_FOREVER, 1.0f);
	return true;
}

void DemoCreateFixture::box2DAppReady()
{
	createShapeMap();
}

void DemoCreateFixture::createShapeMap()
{
	vector<int> Z = { 1,1,0,
					  0,1,1,
					  0,0,0 };
	vector<int> S = { 0,1,1,
		              1,1,0,
		              0,0,0 };
	vector<int> L = { 1,0,0,
		              1,0,0,
		              1,1,0 };
	vector<int> L2 = { 0,1,0,
		               0,1,1,
		               1,1,0 };
	vector<int> T = { 1,1,1,
		              0,1,0,
		              0,0,0 };
	vector<int> M = { 1,1,1,
		              1,0,1,
		              0,0,0 };
	vector<int> X = { 0,1,0,
		              1,1,1,
		              0,1,0 };
	vector<int> O = { 1,1,0,
		              1,1,0,
		              0,0,0 };
	shapeMapList.push_back(Z);
	shapeMapList.push_back(S);
	shapeMapList.push_back(L);
	shapeMapList.push_back(L2);
	shapeMapList.push_back(T);
	shapeMapList.push_back(M);
	shapeMapList.push_back(X);
	shapeMapList.push_back(O);
}

b2Body * DemoCreateFixture::createBody(const b2Vec2 & pos, std::vector<int> map)
{
	b2BodyDef* bd = new b2BodyDef;
	bd->type = b2BodyType::b2_dynamicBody;
	bd->position = b2Vec2(pos.x*LSYEasyWorld::PTOM, pos.y*LSYEasyWorld::PTOM);

	b2FixtureDef* fd = new b2FixtureDef;
	fd->density = 1;
	fd->restitution = 0;

	b2Body* body = pWorld->CreateBody(bd);
	
	float bx = 0, by = 0;
	b2Vec2 center;
	b2PolygonShape* shape = new b2PolygonShape;
	
	for (int i = 0; i < 3; ++i)
	{
		for (int j = 0; j < 3; ++j)
		{
			if (map[i * 3 + j] == 1)
			{
				bx = i * boxSize;
				by = j * boxSize;
				center.x = bx * PTM_RADIO;
				center.y = by * PTM_RADIO;
				shape->SetAsBox(boxSize*PTM_RADIO*0.5, boxSize*PTM_RADIO*0.5, center, 0);
				//fd->shape = shape
				body->CreateFixture(shape, 1);
			}
		}
	}

	REALSE_NULL(bd);
	REALSE_NULL(fd);
	REALSE_NULL(shape);
	return body;
}

void DemoCreateFixture::work(float dt)
{
	random_device rad;
	auto size = Director::getInstance()->getWinSize();
	int width = size.width - 100;
	float x = rad() % (width)+50;
	int index = rad() % 8;
	createBody(b2Vec2(x, size.height - 40), shapeMapList[index]);
	drawHeightestLine();
}

void DemoCreateFixture::drawHeightestLine()
{
	float height = 0;
	b2Body* by = pWorld->GetBodyList()->GetNext();
	while (by)
	{
		if (by->GetType() == b2BodyType::b2_dynamicBody)
		{
			b2AABB res = getAABBOfBody(by);
			height = max({ res.upperBound.y,height });
		}
		by = by->GetNext();
	}
	auto size = Director::getInstance()->getWinSize();
	p1.Set(0, height);
	p2.Set(size.width*PTM_RADIO, height);
}

b2AABB DemoCreateFixture::getAABBOfBody(b2Body * body)
{
	b2AABB res;
	b2Fixture* f = body->GetFixtureList();
	res = f->GetAABB(0);
	while (f)
	{
		res.Combine(f->GetAABB(0));
		f = f->GetNext();
	}
	return res;
}

void DemoCreateFixture::draw(cocos2d::Renderer * renderer, const cocos2d::Mat4 & transform, uint32_t flags)
{
	AbstractBox2DTest::draw(renderer, transform, flags);
	pDebug->DrawSegment(p1, p2, b2Color(1, 0, 0));
}